﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using ReadWriteCsv;

namespace StockAnomalyDetector
{
    class RelayRecord : Record
    {
        public int RelayTime; // 接力的次数
        public double PriceChange; // 接力过程对股价的影响
        public string AppearanceTime; // 开始时间+3次接力：93030-104545-105151-111012

        public override string ToString()
        {
            return string.Format("{0},{1},{2:F2},{3}", base.ToString(), RelayTime, PriceChange, AppearanceTime);
        }
    }

    /*
     * Relay：对敲操作。一方买一方卖，交替操作，哄抬或打压股价
     */
    class Relay : Pattern
    {
        public Relay(CsvRow row) : base(row)
        {
        }

        public static List<string> exceptionList = new List<string>() { "stockCode,date,startTime,endTime,relayTime,priceChange,appearanceTime" };//暂时存储所有Csv文件里的Repetition异常
        public static CsvFileWriter writer = new CsvFileWriter(@"D:\股票数据\" + "relay" + ".csv");

        private double total;
        private int count;
        private char target = 'N'; // B或S。初始为N，not defined。
        private int startTime;
        private double startPrice;
        private int relayTime;
        private int lastTime; // 最后一次发现目标大额交易的时间

        List<int> relayTimes = new List<int>();
        List<double> priceChanges = new List<double>();
        List<int> startTimes = new List<int>();
        List<int> endTimes = new List<int>();

        private List<string> appearanceTimes = new List<string>(); // 若发现异常，则将接力时间组织好，放入其中
        private List<string> appearanceTime = new List<string>(); // 暂存接力时间

        public override void Analyze()
        {
            ParseRow();

            total += price * quantity;
            count++;
            double avg = total / count; // 当前成交额的平均值

            if (price * quantity > avg * 50) // 发现大额交易
            {
                if (target == 'N') // 第一次发现大额交易
                {
                    startTime = lastTime = time;
                    appearanceTime.Add(startTime.ToString());
                    startPrice = price;
                    target = BorS == 'B' ? 'S' : 'B';
                }
                else if (Utils.GetSpan(lastTime, time).TotalMinutes > 5) // 连续操作时间间隔超过一定时间，记录已有结果，再重置
                {
                    if (relayTime >= 3) // 若接力达一定次数，则记录异常
                    {
                        relayTimes.Add(relayTime);
                        priceChanges.Add(price - startPrice);
                        startTimes.Add(startTime);
                        endTimes.Add(time);
                        appearanceTimes.Add(string.Join("-", appearanceTime.ToArray())); // 组织接力时刻
                    }
                    // 重置，把当前这次作为第一次
                    relayTime = 0;
                    startTime = time;
                    startPrice = price;
                    target = BorS == 'B' ? 'S' : 'B';

                    appearanceTime = new List<string> { startTime.ToString() }; // 更新暂存表
                }
                else if (BorS == target) // 找到目标
                {
                    relayTime++;
                    lastTime = time;
                    appearanceTime.Add(lastTime.ToString());
                    target = BorS == 'B' ? 'S' : 'B'; // 更新目标
                }
                
            }
        }

        public override void End(string sourceName)
        {
            // 最后的处理工作，把所有异常数据扔进repetitionList，待外部UpdateExceptionRecord函数统一操作
            for (int i = 0; i < relayTimes.Count; i++)
            {
                Record record = new RelayRecord()
                {
                    stockcode = Convert.ToString(Regex.Match(sourceName, @"[A-Z]{2}\d{6}")),
                    date = Convert.ToString(Regex.Match(sourceName, @"\d{8}")),
                    startTime = startTimes[i],
                    endTime = endTimes[i],
                    RelayTime = relayTimes[i],
                    PriceChange = priceChanges[i],
                    AppearanceTime = appearanceTimes[i]
                };
                Console.WriteLine("Relay: "+record);
                exceptionList.Add(record.ToString());
            }
        }
    }
}
